package pub.tbc.api.handler;

import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import lombok.extern.slf4j.Slf4j;
import pub.tbc.api.invoker.Invoker;
import pub.tbc.api.invoker.InvokerFactory;
import pub.tbc.api.invoker.protocol.http.NettyHttpUtil;


/**
 * netty处理链最后一环，请求转发；
 * 需要：具体协议的请求转发组件，获取该组件需要协议转换组件
 *
 * @author tbc on 2017/3/3 13:10:53.
 */
@Slf4j
public class InvokerHandler5 extends SimpleChannelInboundHandler<FullHttpRequest> {
    // 具体的的调用器应该按配置生成（约定默认值），交由专门的工厂处理
    private Invoker invoker = InvokerFactory.getInvoker();
    private Channel outboundChannel;

    @Override
    public void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest msg) throws Exception {
        log.info("event read - 调用Invoker组件");
        final Channel inboundChannel = ctx.channel();
        invoker.invoke(ctx, msg);
        log.debug("主线程处理结束...");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
        log.error("发生异常： {}", cause.getMessage());
        context.close();
        context.fireChannelRead(cause);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.out.println("[断开连接]channelInactive...");
    }

    @Override
    public void channelActive(ChannelHandlerContext context) throws Exception {
        log.debug("[建立连接]channelActive...");
        super.channelActive(context);
    }

    private static class BackendHandlerInitializer extends ChannelInitializer<SocketChannel> {

        final Channel inboundChannel;

        public BackendHandlerInitializer(Channel inboundChannel) {
            this.inboundChannel = inboundChannel;
        }

        @Override
        public void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(new HttpClientCodec())
                    .addLast(new HttpObjectAggregator(1024 * 1024))
                    .addLast(new HttpBackendHandler(inboundChannel));
        }
    }

    private static class HttpBackendHandler extends SimpleChannelInboundHandler<FullHttpResponse> {

        private final Channel inboundChannel;

        public HttpBackendHandler(Channel inboundChannel) {
            this.inboundChannel = inboundChannel;
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            log.debug("[代理处理器] is Active!");
            super.channelActive(ctx);
        }

        @Override
        public void channelRead0(final ChannelHandlerContext ctx, FullHttpResponse msg) throws Exception {
            log.info("[代理处理器]收到第三方响应: {}", msg);
            inboundChannel.writeAndFlush(msg.retain()).addListener(new ChannelFutureListener() {
                public void operationComplete(ChannelFuture future) throws Exception {
                    log.debug(".......................................");
                    if (!future.isSuccess()) {
                        future.channel().close();
                    }
                }
            });
        }

        @Override
        public void channelInactive(ChannelHandlerContext ctx) {
            log.debug("[代理连接断开]Backend Handler destroyed!");
            NettyHttpUtil.closeOnFlush(inboundChannel);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            NettyHttpUtil.closeOnFlush(ctx.channel());
        }
    }


}
